package com.authine.cloudpivot.ext.controller.DealingUnitInformation;

import com.alibaba.fastjson.JSONObject;
import com.authine.cloudpivot.engine.api.facade.BizObjectFacade;
import com.authine.cloudpivot.engine.api.model.organization.UserModel;
import com.authine.cloudpivot.engine.api.model.runtime.BizObjectCreatedModel;
import com.authine.cloudpivot.engine.api.model.runtime.WorkItemModel;
import com.authine.cloudpivot.engine.api.model.runtime.WorkflowInstanceModel;
import com.authine.cloudpivot.engine.enums.status.SequenceStatus;
import com.authine.cloudpivot.ext.Utils.CustomSchemaCode;
import com.authine.cloudpivot.ext.Utils.Utils;
import com.authine.cloudpivot.ext.modules.AreaCode;
import com.authine.cloudpivot.ext.service.CloudSqlService;
import com.authine.cloudpivot.web.api.controller.base.BaseController;
import com.authine.cloudpivot.web.api.view.ResponseResult;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.MapUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.time.DateFormatUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.util.ObjectUtils;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.*;

/**
 * 总公司往来单位基础信息
 */

@Slf4j
@RestController
@RequestMapping("/public/HeadOfficeDealingUnitController")
public class HeadOfficeDealingUnitController extends BaseController {

    @Autowired
    CloudSqlService sqlService;

    /**
     * 根据地区代码获取基础信息及上级代码信息......
     *
     * @param majorAreaCode
     * @return
     */
    @RequestMapping("getMajorAreaInfo")
    public ResponseResult<Map<String, Object>> getMajorAreaInfo(@RequestParam String majorAreaCode) {
        BizObjectFacade bizObjectFacade = getBizObjectFacade();
        String tableName = bizObjectFacade.getTableName(CustomSchemaCode.REGION_CODE_BASE);
        StringBuffer sql = new StringBuffer("select * from ").append(tableName).append(" where regionCode = '")
                .append(majorAreaCode).append("' ORDER BY modifiedTime desc limit 1");
        Map<String, Object> map = sqlService.getMap(sql.toString());
        String superiorRegionCode = (String) map.get("superiorRegionCode");//上级地区代码
        if (StringUtils.isNotBlank(superiorRegionCode)) {
            getInfo(majorAreaCode, map);
        }
        return getOkResponseResult(map, "success");

    }

    private Map<String, Object> getInfo(String majorAreaCode, Map<String, Object> params) {
        if ("G".equals(majorAreaCode)) {
            return params;
        }
        BizObjectFacade bizObjectFacade = getBizObjectFacade();
        String tableName = bizObjectFacade.getTableName(CustomSchemaCode.REGION_CODE_BASE);
        StringBuffer sql = new StringBuffer("select * from ").append(tableName).append(" where regionCode = '")
                .append(majorAreaCode).append("' ORDER BY modifiedTime desc limit 1");
        Map<String, Object> map = sqlService.getMap(sql.toString());
        if (map == null || map.size() == 0) {
            return params;
        }
        String superiorRegionCode = (String) map.get("superiorRegionCode");//上级地区代码
        String type = (String) map.get("type");//类别
        String regionName = (String) map.get("regionName");//名称
        String regionCode = (String) map.get("regionCode");//地区代码
        String typeCode = AreaCode.getCode(type);
        params.put(type, regionName);
        params.put(typeCode, regionCode);
        if (StringUtils.isNotBlank(superiorRegionCode)) {
            getInfo(superiorRegionCode, params);
        }
        return params;
    }


    /**
     * 总公司往来单位基础信息  审批流完成后 数据写到-总公司往来单位基础信息 基础表，补全基础表的数据
     */
    @RequestMapping("finish")
    public void finish(String bizId) {
        BizObjectCreatedModel bizObject = getBizObjectFacade().getBizObject(CustomSchemaCode.headOfficeDealingUnit, bizId);
        //headOfficeDealingUnitDetail  总公司往来单位基础信息 子表
        List<Map<String, Object>> list = (List<Map<String, Object>>) bizObject.get(CustomSchemaCode.headOfficeDealingUnitDetail);
        String now = LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
        String approval = "";
//        String approval = getFileBaseInfoWorkFlowApproval(bizObject);
        for (Map<String, Object> map : list) {
            try {
                //将子表中数据处理，随后更新至【总公司往来单位基础信息 基础表】，需要判断是否存在
                Map<String, Object> data = Utils.fileInfoBaseMap(map, approval);
                //主责岗A管理员A
                data.put("postA_Administrator_A", bizObject.get("postA_Administrator_A"));
                //主责岗A管理员B
                data.put("postA_Administrator_B", bizObject.get("postA_Administrator_B"));
                //主责岗B管理员A
                data.put("postB_Administrator_A", bizObject.get("postB_Administrator_A"));
                //主责岗B管理员B
                data.put("postB_Administrator_B", bizObject.get("postB_Administrator_B"));
                String id = existsBizObject(data);
                if (StringUtils.isNotBlank(id)) {
                    data.put("id", id);
                }
                BizObjectCreatedModel model = new BizObjectCreatedModel(CustomSchemaCode.headOfficeDealingUnitBas, data, false);
                model.setSequenceStatus(SequenceStatus.COMPLETED.name());
                id = getBizObjectFacade().saveBizObject(CustomSchemaCode.adminUserId, model, false);
                log.info("总公司往来单位基础信息 基础表-新增成功");

                //调用存储过程，入参id是指 总公司往来单位基础信息 基础表的表单id，每一条总公司往来单位基础信息的子表数据都会生成一条 总公司往来单位基础信息 基础表 的主表数据
                callProcess(id);
//                String headOfficeDealingUnitBasicTableName = getBizObjectFacade().getTableName(CustomSchemaCode.headOfficeDealingUnitDetail);
//                StringBuffer updateFidSql = new StringBuffer("update ").append(headOfficeDealingUnitBasicTableName).append(" set fid='")
//                        .append(fid).append("' where id='").append(id).append("';");
//                sqlService.update(updateFidSql.toString());
            } catch (Exception e) {
                log.info("总公司往来单位基础信息 基础表-操作失败，数据:\n{}", JSONObject.toJSONString(map));
                log.info(e.getMessage(), e);
            }
        }
    }

    @RequestMapping("toVoid")
    public void toVoid(String bizId) {
        BizObjectCreatedModel bizObject = getBizObjectFacade().getBizObject(CustomSchemaCode.voidHeadOfficeDealing, bizId);
        List<Map<String, Object>> list = (List<Map<String, Object>>) bizObject.get(CustomSchemaCode.voidHeadOfficeDealingDetail);
        String now = LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
        //获取审批人
        String approval = getFileBaseInfoWorkFlowApproval(bizObject);
        for (Map<String, Object> map : list) {
            try {
                //将子表中数据处理，随后更新至【总公司往来单位基础信息 基础表】，需要判断是否存在
                Map<String, Object> data = Utils.fileInfoBaseMap(map, approval);
                //主责岗A管理员A
                data.put("postA_Administrator_A", bizObject.get("postA_Administrator_A"));
                //主责岗A管理员B
                data.put("postA_Administrator_B", bizObject.get("postA_Administrator_B"));
                //主责岗B管理员A
                data.put("postB_Administrator_A", bizObject.get("postB_Administrator_A"));
                //主责岗B管理员B
                data.put("postB_Administrator_B", bizObject.get("postB_Administrator_B"));
                String id = existsBizObject(data);
                if (StringUtils.isNotBlank(id)) {
                    data.put("id", id);
                }

                BizObjectCreatedModel model = new BizObjectCreatedModel(CustomSchemaCode.headOfficeDealingUnitBas, data, false);
                model.setSequenceStatus(SequenceStatus.CANCELED.name());
                id = getBizObjectFacade().saveBizObject(CustomSchemaCode.adminUserId, model, false);
                log.info("总公司往来单位基础信息 基础表  作废操作成功 ");
                //调用存储过程
                callProcessToVoid(id);

                // 删除总公司级往来单位档案公司点检汇总记录表、公司往来单位档案点检汇总记录
                Object functionCode = data.get("dealingUnitCode");
                String tableName1 = this.getBizObjectFacade().getTableName(CustomSchemaCode.OFFICE_UNIT_BASE_1);
                String tableName2 = this.getBizObjectFacade().getTableName(CustomSchemaCode.OFFICE_UNIT_BASE_2);
                String tableName3 = this.getBizObjectFacade().getTableName(CustomSchemaCode.COMPANY_UNIT_BASE);
                String deleteSql1 = "delete from "+tableName1+" where functionCode = "+functionCode+"";
                String deleteSql2 = "delete from "+tableName2+" where functionCode = "+functionCode+"";
                String deleteSql3 = "delete from "+tableName3+" where functionCode = "+functionCode+"";
                sqlService.update(deleteSql1);
                sqlService.update(deleteSql2);
                sqlService.update(deleteSql3);

            } catch (Exception e) {
                String companyNumber = (String) map.get("companyNumber");
                String personNumber = (String) map.get("personNumber");
                log.info("总公司往来单位基础信息 基础表  作废操作失败 personNumber={},companyNumber={}", personNumber, companyNumber);
                log.info(e.getMessage(), e);
            }

        }
    }


    /**
     * 调用存储过程
     * ----总公司往来单位基础信息
     * exec     SyncSupplierInfo
     *
     * @AreaCode nvarchar(100),   ----地区代码
     * @Number nvarchar(100),   ----往来单位代码
     * @Name nvarchar(100),   ----往来单位名称
     * @simplename nvarchar(100),   ----简称
     * @ForeignName nvarchar(100),  ----外文名称
     * @begdate datetime,   ----启用时间
     * @suppstatus nvarchar(10),  ----状态 0 禁用  1  未核准  2 核准
     * @StatusDesc nvarchar(200),  ----状态说明
     * @MainAddressCode nvarchar(100),  ----主地址代码
     * @MainAddress nvarchar(500),  ----主地址
     * @zipcode nvarchar(100),  ----主地址邮编
     * @MainComid nvarchar(100),  ----主责公司id
     * @MainDeptid nvarchar(100),  ----主责部门id
     * @posacode nvarchar(100),  ----主责岗A代码
     * @posbcode nvarchar(100),  ----主责岗B代码
     * @MainPerson nvarchar(100),  ----主责人
     * @auditor nvarchar(100),  ----02.0100 张三
     * @countrycode nvarchar(50),  ----国家代码
     * @provincecode nvarchar(50),  ----省份代码
     * @citycode nvarchar(50),  ----城市代码
     * @regioncode nvarchar(50)  ----区县代码
     */
    private void callProcess(String bizId) {
        if (StringUtils.isEmpty(bizId)) {
            return;
        }
        //编写sql
        String tableName = getBizObjectFacade().getTableName(CustomSchemaCode.headOfficeDealingUnitBas);
        StringBuilder sql = new StringBuilder("SELECT * from ")
                .append(tableName).append(" where id ='")
                .append(bizId).append("';");
        //查询到入参
        Map<String, Object> map = sqlService.getMap(sql.toString());
        log.info("[总公司往来单位基础信息]存储过程入参map={}", map);
        //调用存储过程
        String areaCode = MapUtils.getString(map, "areaCode", "");//地区代码
        String dealingUnitCode = MapUtils.getString(map, "dealingUnitCode", "");//往来单位代码
        String dealingUnitName = MapUtils.getString(map, "dealingUnitName", "");//往来单位名称
        String abbreviation = MapUtils.getString(map, "abbreviation", "");//简称
        String foreignName = MapUtils.getString(map, "foreignName", "");//外文名称
//        String enabledTime = (Date) map.get("enabledTime") == null ? "" : DateFormatUtils.format((Date) map.get("enabledTime"), "yyyy-MM-dd");//启用时间


        LocalDateTime enabledTimeTemp = (LocalDateTime) map.get("enabledTime");
        String enabledTime =  ObjectUtils.isEmpty(enabledTimeTemp) ? "" : enabledTimeTemp.toLocalDate().toString();


        String state = MapUtils.getString(map, "state", "");//状态 0 禁用  1  未核准  2 核准
        String stateValue = "";
        switch (state) {
            case "禁用":
                stateValue = "0";
                break;
            case "未核准":
                stateValue = "1";
                break;
            case "核准":
                stateValue = "2";
                break;
        }
        String description = MapUtils.getString(map, "description", "");//状态说明
        String majorAreaCode = MapUtils.getString(map, "majorAreaCode", "");//主地址代码
        String primaryAddress = MapUtils.getString(map, "primaryAddress", "");//主地址
        String masterAddressPostcode = MapUtils.getString(map, "masterAddressPostcode", "");//主地址邮编
        String company = MapUtils.getString(map, "companyNumber", "");//主责公司代码
        String responsibleDeptFid = MapUtils.getString(map, "responsibleDeptFNumber", "");//主责部门代码
        String postANumber = MapUtils.getString(map, "postANumber", "");//主责岗A代码
        String postBNumber = MapUtils.getString(map, "postBNumber", "");//主责岗B代码
        String responsiblePersonName = MapUtils.getString(map, "responsiblePersonName", "");//主责人
        String approval = MapUtils.getString(map, "approval", "");//审批人 02.0100 张三
        String countryCode = MapUtils.getString(map, "countrycode", "");
        String provinceCode = MapUtils.getString(map, "provincecode", "");
        String cityCode = MapUtils.getString(map, "citycode", "");
        String districtCode = MapUtils.getString(map, "districtcode", "");
        String execSql = String.format("exec [HG_LINK].[hg].[dbo].SyncSupplierInfo '%s','%s','%s','%s','%s','%s','%s','%s','%s','%s','%s','%s','%s','%s','%s','%s','%s','%s','%s','%s','%s'",
                areaCode, dealingUnitCode, dealingUnitName, abbreviation, foreignName,
                enabledTime, stateValue, description, majorAreaCode, primaryAddress,
                masterAddressPostcode, company, responsibleDeptFid, postANumber, postBNumber,
                responsiblePersonName, approval, countryCode, provinceCode, cityCode, districtCode);
        log.info("\n==========准备调用[总公司往来单位基础信息]存储过程:{}", execSql);
        sqlService.execute(CloudSqlService.htEas, execSql);
        log.info("\n=============[总公司往来单位基础信息]存储过程执行完成");
    }

    /**
     * 调用作废存储过程
     * --------总公司往来单位作废
     * exec  SuppDisable
     *
     * @Number nvarchar(100)            ----往来单位代码
     */
    private void callProcessToVoid(String bizId) {
        if (StringUtils.isEmpty(bizId)) {
            return;
        }
        //编写sql
        String tableName = getBizObjectFacade().getTableName(CustomSchemaCode.headOfficeDealingUnitBas);
        StringBuilder sql = new StringBuilder("SELECT * from ")
                .append(tableName).append(" where id ='")
                .append(bizId).append("';");
        //查询到入参
        Map<String, Object> map = sqlService.getMap(sql.toString());
        log.info("[总公司往来单位作废]存储过程入参map={}", map);
        //准备调用存储过程的入参
        String dealingUnitCode = MapUtils.getString(map, "dealingUnitCode", "");//fid
        String execSql = String.format("exec [HG_LINK].[hg].[dbo].SuppDisable '%s'",
                dealingUnitCode);
        log.info("\n==========准备调用[总公司往来单位作废]存储过程:{}", execSql);
        sqlService.execute(CloudSqlService.htEas, execSql);
        log.info("\n=============[总公司往来单位作废]存储过程执行完成");
    }

//    /**
//     * 调用作废存储过程
//     * --------总公司往来单位基础信息   作废
//     * exec  ToDoListDisable
//     *
//     * @Companyid nvarchar(100),            ----公司FID
//     * @item nvarchar(200),            ----事项
//     * @RegisDate nvarchar(100),            ----登记日期
//     * @RelevantFileFID nvarchar(100)            ----相关档案FID
//     */
//    private void callProcessToVoid(String bizId) {
//
//        if (StringUtils.isEmpty(bizId)) {
//            return;
//        }
//        //编写sql
//        String tableName = getBizObjectFacade().getTableName(CustomSchemaCode.headOfficeDealingUnitDetail);
//        StringBuilder sql = new StringBuilder("SELECT * from ")
//                .append(tableName).append(" where id ='")
//                .append(bizId).append("';");
//        //查询到入参
//        Map<String, Object> map = sqlService.getMap(sql.toString());
//        log.info("入参map={}", map);
//
//        //准备调用存储过程的入参
//        String company = MapUtils.getString(map, "company", "");//公司FID
//        String event = MapUtils.getString(map, "event", "");//事项
//        Date registrationDateTemp = (Date) map.get("registrationDate");//登记日期
//        String registrationDate = registrationDateTemp == null ? null : DateFormatUtils.format(registrationDateTemp, "yyyy-MM-dd");
//        String relatedFileFID = MapUtils.getString(map, "relatedFileFID", "");//相关档案FID
//
//        //检查存储过程的入参
//        Assert.isFalse(StringUtils.isEmpty(company), "{}不能为空", "company");
//        Assert.isFalse(StringUtils.isEmpty(event), "{}不能为空", "event");
//        Assert.isFalse(StringUtils.isEmpty(registrationDate), "{}不能为空", "registrationDate");
//        Assert.isFalse(StringUtils.isEmpty(relatedFileFID), "{}不能为空", "relatedFileFID");
//
//        //拼接sql
//        String execSql = String.format("exec [HG_LINK].[hg].[dbo].ToDoListDisable '%s','%s','%s','%s'",
//                company, event, registrationDate, relatedFileFID);
//
//        log.info("\n==========准备调用[总公司往来单位基础信息   作废]存储过程:{}", execSql);
//        sqlService.execute(CloudSqlService.htEas, execSql);
//        log.info("\n=============[总公司往来单位基础信息   作废]存储过程执行完成");
//
//    }

    /**
     * 查询审批人,返回  员工号+姓名
     *
     * @param bizObject
     * @return
     */
    private String getFileBaseInfoWorkFlowApproval(BizObjectCreatedModel bizObject) {
        WorkflowInstanceModel instanceModel = getWorkflowInstanceFacade().getByObjectId(bizObject.getId());
        List<WorkItemModel> workItems = getWorkflowInstanceFacade().getWorkItems(instanceModel.getId(), true);
        final String finalActivityCode = "Activity20";
        Optional<WorkItemModel> first = workItems.stream().filter(a -> a.getActivityCode().equals(finalActivityCode)).findFirst();
        String participant = null;
        if (first.isPresent()) {
            WorkItemModel workItemModel = first.get();
            participant = workItemModel.getParticipant();
        }

        if (participant == null) {
            final String finalActivityCode2 = "Activity15";
            Optional<WorkItemModel> second = workItems.stream().filter(a -> a.getActivityCode().equals(finalActivityCode2)).findFirst();
            if (second.isPresent()) {
                WorkItemModel workItemModel = second.get();
                participant = workItemModel.getParticipant();
            }
        }


        if (participant == null) {
            participant = bizObject.getCreater().getId();
        }

        UserModel user = getOrganizationFacade().getUser(participant);


        return new StringBuilder(user.getEmployeeNo()).append("　").append(user.getName()).toString();
    }


    /**
     * 判断是否已存在
     *
     * @return
     */
    private String existsBizObject(Map data) {

        //往来单位代码
        String dealingUnitCode = (String) data.get("dealingUnitCode");

        String tableName = getBizObjectFacade().getTableName(CustomSchemaCode.headOfficeDealingUnitBas);

        StringBuilder sql = new StringBuilder("select id  from ").append(tableName).append(" where dealingUnitCode ='").append(dealingUnitCode).append("' order by createdTime desc limit 1;");

        Map<String, Object> map = sqlService.getMap(sql.toString());

        return (String) map.get("id");
    }

    /**
     * 转换成  总公司往来单位基础信息 基础表 的数据
     *
     * @param map
     * @param bizObject
     * @param auditDate
     * @return
     */
    private Map<String, Object> fileInfoBaseMap(Map<String, Object> map, BizObjectCreatedModel bizObject, String auditDate, String approval) {
        Map<String, Object> data = new HashMap<>();
        //审批人
        data.put("approval", approval);
        //审批时间
        data.put("auditDate", auditDate);

        //地区代码
        data.put("relevanceAreaCode", map.get("relevanceAreaCode"));
        //地区代码
        data.put("areaCode", map.get("areaCode"));
        //序号
        data.put("serialNumber", map.get("serialNumber"));
        //往来单位代码
        data.put("dealingUnitCode", map.get("dealingUnitCode"));
        //往来单位
        data.put("dealingUnitName", map.get("dealingUnitName"));
        //简称
        data.put("abbreviation", map.get("abbreviation"));
        //外文名称
        data.put("foreignName", map.get("foreignName"));
        //启用时间
        data.put("enabledTime", map.get("enabledTime"));
        //状态
        data.put("state", map.get("state"));
        //说明
        data.put("description", map.get("description"));
        //主地址代码
        data.put("relevanceMajorAreaCode", map.get("relevanceMajorAreaCode"));
        //主地址代码
        data.put("majorAreaCode", map.get("majorAreaCode"));
        //主地址区号
        data.put("primaryAddressAreaCode", map.get("primaryAddressAreaCode"));
        //国家
        data.put("country", map.get("country"));
        //省份
        data.put("province", map.get("province"));
        //城市
        data.put("city", map.get("city"));
        //区县
        data.put("district", map.get("district"));
        //主地址
        data.put("primaryAddress", map.get("primaryAddress"));
        //主地址邮编
        data.put("masterAddressPostcode", map.get("masterAddressPostcode"));
        //主责公司
        data.put("company", map.get("company"));
        //主责公司
        data.put("companyNumber", map.get("companyNumber"));
        //主责部门代码
        data.put("responsibleDeptFid", map.get("responsibleDeptFid"));
        //主责部门代码
        data.put("responsibleDeptFNumber", map.get("responsibleDeptFNumber"));
        //主责部门
        data.put("responsibleDeptName", map.get("responsibleDeptName"));
        //主责岗A代码
        data.put("relevancePostA", map.get("relevancePostA"));
        //主责岗A代码
        data.put("postANumber", map.get("postANumber"));
        //主责岗A
        data.put("postAName", map.get("postAName"));
        //主责岗A管理员A
        data.put("postA_Administrator_A", bizObject.get("postA_Administrator_A"));
        //主责岗A管理员B
        data.put("postA_Administrator_B", bizObject.get("postA_Administrator_B"));
        //主责岗B代码
        data.put("relevancePostB", map.get("relevancePostB"));
        //主责岗B代码
        data.put("postBNumber", map.get("postBNumber"));
        //主责岗B
        data.put("postBName", map.get("postBName"));
        //主责岗B管理员A
        data.put("postB_Administrator_A", bizObject.get("postB_Administrator_A"));
        //主责岗B管理员B
        data.put("postB_Administrator_B", bizObject.get("postB_Administrator_B"));
        //主责人
        data.put("responsiblePersonName", map.get("responsiblePersonName"));
        return data;
    }

}
